<!DOCTYPE html>
<!--
Copyright (c) 2013 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->
<link rel="import" href="/tracing/base/base.html">
<script>
'use strict';

tr.exportTo('tr.model', function() {
  function StackFrame(parentFrame, id, title, colorId, opt_sourceInfo) {
    if (id === undefined) {
      throw new Error('id must be given');
    }
    this.parentFrame_ = parentFrame;
    this.id = id;
    this.title_ = title;
    this.colorId = colorId;
    this.children = [];
    this.sourceInfo_ = opt_sourceInfo;

    if (this.parentFrame_) {
      this.parentFrame_.addChild(this);
    }
  }

  StackFrame.prototype = {
    get parentFrame() {
      return this.parentFrame_;
    },

    get title() {
      if (this.sourceInfo_) {
        const src = this.sourceInfo_.toString();
        return this.title_ + (src === '' ? '' : ' ' + src);
      }
      return this.title_;
    },

    /**
     * Attempts to find the domain of the origin of the script either from this
     * stack trace or from its ancestors.
     */
    get domain() {
      let result = 'unknown';
      if (this.sourceInfo_ && this.sourceInfo_.domain) {
        result = this.sourceInfo_.domain;
      }
      if (result === 'unknown' && this.parentFrame) {
        result = this.parentFrame.domain;
      }
      return result;
    },

    get sourceInfo() {
      return this.sourceInfo_;
    },

    set parentFrame(parentFrame) {
      if (this.parentFrame_) {
        Polymer.dom(this.parentFrame_).removeChild(this);
      }
      this.parentFrame_ = parentFrame;
      if (this.parentFrame_) {
        this.parentFrame_.addChild(this);
      }
    },

    addChild(child) {
      this.children.push(child);
    },

    removeChild(child) {
      const i = this.children.indexOf(child.id);
      if (i === -1) {
        throw new Error('omg');
      }
      this.children.splice(i, 1);
    },

    removeAllChildren() {
      for (let i = 0; i < this.children.length; i++) {
        this.children[i].parentFrame_ = undefined;
      }
      this.children.splice(0, this.children.length);
    },

    /**
     * Returns stackFrames where the most specific frame is first.
     */
    get stackTrace() {
      const stack = [this];
      let cur = this.parentFrame;
      while (cur) {
        stack.push(cur);
        cur = cur.parentFrame;
      }
      return stack;
    },

    getUserFriendlyStackTrace() {
      return this.stackTrace.map(function(x) { return x.title; });
    }
  };

  return {
    StackFrame,
  };
});
</script>
